#A Cut-like tool.
import sys
import argparse
import warnings
import re

parser = argparse.ArgumentParser(
	description='Cut-like tool',
	usage='To output the stream/file by columns')

parser.add_argument(
	'-m',
	dest='mod',
	choices={'fields', 'cols'},
	required=True,
	help='\n\tMode[Filed OR Cols]',
)

parser.add_argument(
        '-d',
        dest='delimeter',
        default='\n',
        help='\n\tDelimeter for mode -f',
)
parser.add_argument(
	'field',
        default='0',
	help="[LIST] range(field) of the txt"
)

parser.add_argument(
	'file',
	help="[FILE]"
)

parser.add_argument(
        '->',
        dest='redirect',
        action='store',
        default=sys.stdout,
        help="[FILE_STREAM]Redirect to ...Default::StdOut"
)


args = parser.parse_args()
file = args.file
mod = args.mod
field = args.field
delim = args.delimeter
redirectTo = args.redirect

#================Declaring========================
'''
class FieldRange:
	def __init__(self, ranger:list):
		
		if 1 == len(ranger):
			self._FLD = "POS"
		elif 2 == len(ranger):
			self._FLD = "RANGE"
		else:
			warnings.warn("Range Wrong")
			exit()
	def __repr__(self) -> str:
		return f"{self.lo}-{self.hi}"
	
#Instance of FieldRange, We need to parse the commmand line
#TODO Paser!!!!!
'''

funcs = {
        'f':fieldcut,
        'c':ccut,
        'b':bcut,
        }

if __name__ == '__main__':

    operator = func[mod]
    field = get_field(field)
    cats = operator(file, parsed_field, delim)
    print(cats, file=file)
#Considering the possible redirect, we have to store 
#the txt in cats instead of output it to the stdout stream.


#==============Range Parser=======================
def get_field(cmd:str)->tuple:
    """
Valid Args:
    1-2, 3-4, 3:4, 4:7, 4%7, 4to7 
Invalid Args
    1>>2>>3, 1:2:3, 1:4,5
    """
    cnnctr_state = False#The state of matching connectors in the given field argument
    connector = [':', '-']
    interval = re.findall(r'\d+', cmd)

    if 2 < len(interval) or None == interval:
        warnings.warn("cut: fields are numbered from 1 ")
        return 0,
    elif None != interval:
        return interval

              


    
#TODO in future version, the function supports 1:2:3...Using Meta Programming...
	

#===================Do Cutting================
def fieldcut(file, delimeter:str, field:list, red, split_mode=True):
    """
    asd}asd}ffgd}
    ass}fff}ssss}
    if delimeter = }
        field = 1->2:
        STD out:
    asd}asd
    ass}fff

    if delimeter = the default value"\n":
    asd}asd}ffgd}
    ass}fff}ssss}
    """
    #All delimeter should be a single char
    delim_splits = rex_convert(delimeter)
    delim_keep, counts = rex_convert(delimeter, throw_delim=False)
    fld_start, fld_end = field[0] - 1, field[-1] - 1

    if split_mod:
        #throw delimeters:
        prog = re.split(delim_splits)
        with open(file, 'r') as f:
        #c is the current charactor
            for line in f.readlines():
                tmpline = prog.split(line)
                for i in range(fld_start, fld_end + 1):
                    print(tmpline[i], end=' ')

    else:
        #keep delimeters:
        """
        2-4 cols:  c1:c2,c3|c4{c5} ==> print(c2,c3|c4)
        """
        prog = re.split(delim_keep)
        with open(file, 'r') as f:
            for line in f.readlines():
                tmpline = prog.split(line)
                #col1--col3: idx0, 1, 2
                for i in range(2 * fld_start + 1, 
                        , 2 * fld_end + 1, step=2):
                    print(tmpline[i], tmpline[i+1], sep='', end=' ')
                #the last one

def rex_convert(txt:str, throw_delim=True):
    if txt is None:
        return '\n'
    elif throw_delim:
        #Throw away delimeters:
        #enter \s;{' --> (?\s|;|{|')\s*
        for i in range(len(txt) - 1):
            txt[i] += '|'
        return txt.join(('(?', ')\s*'))
        #Save delimeters:
        return txt.join(('[', ']\s*')), len(str(txt))






